#include <iostream>
#include <string>
#include <memory>

class Fruit{
public:
    Fruit(){}
    virtual void name() = 0;
};

class Apple : public Fruit{
public:
    Apple(){}
    void name() override
    {
        std::cout << "我是一个苹果" << std::endl;
    }    
};

class Banana : public Fruit{
public:
    Banana(){}
    void name() override
    {
        std::cout << "我是一个香蕉" << std::endl;
    }
};

class Animals{
public:
    Animals(){}
    virtual void name() = 0;
};

class Lamp : public Animals{
public:
    Lamp(){}
    void name() override
    {
        std::cout << "我是一只山羊" << std::endl;
    }    
};

class Dog : public Animals{
public:
    Dog(){}
    void name() override
    {
        std::cout << "我是一只小狗" << std::endl;
    }    
};

class Factory{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string & name) = 0;
    virtual std::shared_ptr<Animals> getAnimal(const std::string & name) = 0;
};

class FruitFactory : public Factory{
    std::shared_ptr<Fruit> getFruit(const std::string & name)
    {
        if (name == "apple")
        {
            return std::make_shared<Apple>();
        }
        else if (name == "banana")
        {
            return std::make_shared<Banana>();
        }
        return nullptr;
    }

    std::shared_ptr<Animals> getAnimal(const std::string & name)
    {
        return std::shared_ptr<Animals>();
    }
};


class AnimalFactory : public Factory{
    std::shared_ptr<Fruit> getFruit(const std::string & name)
    {
        return std::shared_ptr<Fruit>();
    }

    std::shared_ptr<Animals> getAnimal(const std::string & name)
    {
        if (name == "dog")
        {
            return std::make_shared<Dog>();
        }
        else if (name == "lamp")
        {
            return std::make_shared<Lamp>();
        }
        return nullptr;
    }
};

class FactoryProducer{
public:
    static std::shared_ptr<Factory> create(const std::string &name){
        if (name == "fruit")
        {
            return std::make_shared<FruitFactory>();
        }
        else if (name == "animal")
        {
            return std::make_shared<AnimalFactory>();
        }
        return nullptr;        
    }
};

int main()
{
    std::shared_ptr<Factory> ff = FactoryProducer::create("fruit");
    std::shared_ptr<Fruit> fruit = ff->getFruit("apple");
    fruit->name();
    fruit = ff->getFruit("banana");
    fruit->name();

    std::shared_ptr<Factory> aa = FactoryProducer::create("animal");
    std::shared_ptr<Animals> animal = aa->getAnimal("lamp");
    animal->name();
    animal = aa->getAnimal("dog");
    animal->name();

    return 0;
}
